package com.hjrpc.babyyamall.authserver.web;

import com.google.gson.Gson;
import com.hjrpc.babyyamall.authserver.feign.MemberFeignService;
import com.hjrpc.babyyamall.authserver.vo.UserLoginVo;
import com.hjrpc.common.constant.AuthServerConstant;
import com.hjrpc.common.dto.LoginUserTo;
import com.hjrpc.common.dto.SocialUser;
import com.hjrpc.common.utils.HttpUtils;
import com.hjrpc.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Controller
@Slf4j
public class SSOLoginController {

    @Autowired
    MemberFeignService memberFeignService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @GetMapping("/ssoLogin.html")
    public String ssoLoginHtml(@RequestParam(value = "redirectUrl", defaultValue = "http://babyyamall.com") String redirectUrl,
                               @CookieValue(value = "ssoToken", required = false) String ssoToken, Model model, HttpServletRequest request) {
        if (isValidToken(ssoToken)) {
            String s = redirectUrl.contains("?") ? "&" : "?";
            return "redirect:" + redirectUrl + s + "ssoToken=" + ssoToken;
        }
        model.addAttribute("redirectUrl", redirectUrl);
        return "login";
    }

    @RequestMapping("/ssoLogin")
    public String login(@Validated UserLoginVo userLoginVo, BindingResult result,
                        @RequestParam("redirectUrl") String redirectUrl,
                        @CookieValue(value = "ssoToken", required = false) String ssoToken,
                        RedirectAttributes attributes, HttpServletResponse response) {
        if (result.hasErrors()) {
            attributes.addFlashAttribute("errors", result.getFieldErrors().stream()
                    .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage, (v1, v2) -> v1 + "," + v2)));
            return "redirect:http://auth.babyyamall.com/login.html";
        }
        if (isValidToken(ssoToken)) {
            return "redirect:" + redirectUrl + "?ssoToken=" + ssoToken;
        }
        // 远程调用会员服务
        R r = memberFeignService.login(userLoginVo);
        if (r.isSuccess()) {
            LoginUserTo loginUser = r.getData(LoginUserTo.class);
            log.info("返回的数据：{}", loginUser);
            ssoToken = UUID.randomUUID().toString().replace("-", "");
            redisTemplate.opsForValue().set(AuthServerConstant.AUTH_SSO_TOKEN_PREFIX + ssoToken, loginUser.getId().toString());
            Cookie cookie = new Cookie("ssoToken", ssoToken);
            response.addCookie(cookie);
            return "redirect:" + redirectUrl + "?ssoToken=" + ssoToken;
        }
        String msg = (String) r.get("msg");
        Map<String, String> errors = new HashMap<>();
        errors.put("msg", msg);
        attributes.addFlashAttribute("errors", errors);
        return "redirect:http://auth.babyyamall.com/login.html";
    }

    private boolean isValidToken(String ssoToken) {
        if (StringUtils.isBlank(ssoToken)) {
            return false;
        }
        String memberId = redisTemplate.opsForValue().get(AuthServerConstant.AUTH_SSO_TOKEN_PREFIX + ssoToken);
        return StringUtils.isNotBlank(memberId);
    }

    @GetMapping("/sso/oauth2.0/weibo/success")
    public String weiboSSO(@RequestParam("code") String code,
                           @RequestParam("redirectUrl") String redirectUrl,
                           HttpServletResponse httpServletResponse) {
        // 根据code换取accessToken
        Map<String, String> bodys = new HashMap<>();
        bodys.put("client_id", "116285787");
        bodys.put("client_secret", "e0ba58230a857252a98df13c8f73104a");
        bodys.put("grant_type", "authorization_code");
        bodys.put("redirect_uri", "http://auth.babyyamall.com/oauth2.0/weibo/success");
        bodys.put("code", code);
        try {
            HttpResponse response = HttpUtils.doPost("https://api.weibo.com", "/oauth2/access_token",
                    null, new HashMap<>(), null, bodys);
            if (response.getStatusLine().getStatusCode() == 200) {
                Gson gson = new Gson();
                SocialUser socialUser = gson.fromJson(EntityUtils.toString(response.getEntity()), SocialUser.class);
                // 如果尚未注册会自动注册
                R r = memberFeignService.login(socialUser);
                if (r.isSuccess()) {
                    LoginUserTo loginUser = r.getData(LoginUserTo.class);
                    log.info("返回的数据：{}", loginUser);
                    String ssoToken = UUID.randomUUID().toString().replace("-", "");
                    redisTemplate.opsForValue().set(AuthServerConstant.AUTH_SSO_TOKEN_PREFIX + ssoToken, loginUser.getId().toString());
                    Cookie cookie = new Cookie("ssoToken", ssoToken);
                    httpServletResponse.addCookie(cookie);
                    return "redirect:" + redirectUrl + "?ssoToken=" + ssoToken;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return "redirect:http://auth.babyyamall.com/login.html";
    }

}
